package w3_c2_queue;

/**
 * 不使用size的版本。
 */
public class LoopQueue2 <E> implements Queue<E>{
    E[] data;
    int front,tail;

    public LoopQueue2(int capacity) {
        data = (E[]) new Object[capacity+1];
        front = tail = 0;
    }

    public LoopQueue2(){
        this(10);
    }

    private void resize(int capacity) {
        E[] newData = (E[]) new Object[capacity];
        int i;
        for (i = 0; i < getSize(); i++) {
            newData[i] = data[(i + front) % data.length];
        }
        data = newData;
        front = 0;
        tail = i;
    }
    private int getCapacity(){
        return data.length -1;
    }
    @Override
    public int getSize() {
        //计算size最关键。有两种方式都可实现。
//        return (tail + data.length - front)% data.length;
        if(tail >= front)
            return tail - front;
        else
            return tail + data.length - front;
    }

    @Override
    public boolean isEmpty() {
        return tail == front;
    }

    @Override
    public void enqueue(E e) {
        if((tail + 1) % data.length == front)
            resize(2 * getCapacity());
        data[tail] = e;
        tail = (tail + 1) % data.length;
    }

    @Override
    public E dequeue() {
        if(front == tail)
            throw new IllegalArgumentException("Cannot dequeue from empty queue");
        E res = data[front];
        data[front] = null;
        front = (front +1 )% data.length;
        if(getSize() < getCapacity() /4 && getCapacity() /2 != 0)
            resize(getCapacity() / 2);
        return res;
    }

    @Override
    public E getFront() {
        return data[front];
    }

    @Override
    public String toString() {
        StringBuilder res = new StringBuilder();
        res.append(String.format("LooqQueue, size = %d, capacity = %d\n", getSize(), getCapacity()));
        res.append("front [");
        for (int i = 0; i < getSize(); i++){
            res.append(data[(i+front)% data.length]);
            if(i !=  getSize() -1)
                res.append(", ");
        }
        res.append("] tail\n");
        return res.toString();
    }

    public static void main(String[] args) {
        LoopQueue2<Integer> queue2 = new LoopQueue2<>();
        int n = 20;
        for (int i = 0; i < n; i++) {
            queue2.enqueue(i);
            System.out.println(queue2);
            if (i % 5== 2) {
                queue2.dequeue();
                System.out.println(queue2);
            }
        }
    }
}
